#ifndef xpack_io_file
#define xpack_io_file
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::io_file::inc
#include"adapter/format_output_stream.hpp"
#include"define/base_type.hpp"
#include"dumb/disable_copy.hpp"
#include"dumb/move.hpp"
#include"interface/seqptr.hpp"
#include"lang/cxx.hpp"
#include"macro/xexport.hpp"
#include"macro/xnew.hpp"
#pragma pop_macro("xuser")

namespace mixc::io_file::inc{
    extern u64 length(ixx fd, inc::c08 const & path);
    extern bool is_exist(inc::c08 const & path);
}

namespace mixc::io_file::origin{
    enum class access_mode_t{
        read_only   = 0x1,
        write_only  = 0x2,
        read_write  = 0x3,
    };

    struct file;

    xstruct(
        xname(file),
        xpubb(inc::disable_copy),
        xpubb(inc::format_output_stream<file>),
        xprif(m_fd,     ixx),
        xprif(m_path,   inc::c08)
    )
    private:
        friend inc::format_output_stream<file>;

        void output_text_core(inc::c08 content) const {
            this->write(asciis(content), content->length);
        }
    public:
        xprops()
            xpubgetx(length, uxx){
                xr{
                    if (xthe.m_path->is_empty){
                        return 0;
                    }
                    return inc::length(xthe.m_fd, xthe.m_path);
                }
            };

            xpubgetx(path, inc::c08){
                xr{ return xthe.m_path; }
            };

            xpubgetx(is_exist, bool){
                xr{ return inc::is_exist(xthe.m_path); }
            };

            xpubgetx(is_closed, bool){
                xr{ return xthe.m_fd == 0; }
            };

            xpubgetx(is_open, bool){
                xr{ return xthe.m_fd > 0; }
            };
        $

        xprops_operator()
    public:
        file();
        file(file &&);
        file(inc::c08 path) : m_fd(-1), m_path(path) {}
        file(inc::c08 path, access_mode_t mode, bstate_t * result = nullptr) :
            file(path)/*需要将 m_fd 设置成 -1, 因为 open 内部会调用 close 接口，而此时 m_fd 可能是个整数，会意外关闭其他句柄*/ {
            if (auto status = xthe.open(path, mode); result != nullptr){
                *result = status;
            }
        }
        ~file(){
            xthe.close();
        }

        the_t & operator=(file && value){
            if (this == & value){
                return xthe;
            }

            xthe.close();
            xnew(this) file(inc::move(value));
            return xthe;
        }

        the_t && hand_over() const {
            return (the_t &&)xthe;
        }

        bstate_t open(inc::c08 path, access_mode_t mode) const;
        bstate_t close()                                 const;
        bstate_t seek(i64 offset)                        const;
        bstate_t flush()                                 const;
        uxx      read(voidp buffer, uxx bytes)           const;
        uxx      write(void const * buffer, uxx bytes)   const;

        bstate_t remove()                                const;
        bstate_t move_to(inc::c08 new_path)              const;
        bstate_t move_to_forcedly(inc::c08 new_path)     const;
        bstate_t copy_to(inc::c08 new_path)              const;

        template<class item_t>
        uxx read(inc::seqptr<item_t> seq) const {
            return this->read(seq, seq->length * sizeof(item_t)) / sizeof(item_t);
        }

        template<class item_t>
        uxx write(inc::seqptr<item_t> seq) const {
            return this->write(seq, seq->length * sizeof(item_t)) / sizeof(item_t);
        }
    $
}

#endif

xexport_space(mixc::io_file::origin)
